/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2025. All rights reserved.
 */

import fse from 'fs-extra';
import * as path from 'path';
import { PackageJson } from 'type-fest';

import { BuildArtifactConst, BuildDirConst } from '../../../const/build-directory-const.js';
import { ModuleJson } from '../../../options/configure/module-json-options.js';
import { OhPackageJsonOpt } from '../../../tasks/task/ohos-har-task.js';
import { toUnixPath } from '../../../utils/copy-resources-util.js';
import { getEntryMainFilePath } from '../dependency-manager.js';

import { DependencyBuilder } from './dependency-builder.js';
import { Dependency, DependencyEnum, DependencyType } from './dependency-interface.js';
import ModuleOptObj = ModuleJson.ModuleOptObj;

/**
 * module对应的所有的har依赖的包信息类
 *
 * @since 2022/5/7
 */
export class DefaultNpmDependency implements Dependency {
  private readonly _dependencyName: string;
  private readonly _dependedVersion: string;
  private _lastDependencyName: string | undefined;
  private readonly _dependencyVersion: string;
  private readonly _dependencyRootPath: string;
  private readonly _dependencies: Partial<Record<string, string>>;
  private readonly _pkgJsonPath: string;
  private readonly _pkgJsonName: string;
  private readonly _mainFilePath: string;
  private readonly _typesFilePath: string;
  private readonly _dependencyType: DependencyType;
  private readonly _dependencyEnum: DependencyEnum;
  private readonly _pkgJsonObj: PackageJson;
  private readonly _isLocal: boolean = false;
  private readonly _moduleJsonObj: ModuleOptObj | undefined;
  private readonly _isModuleDependency: boolean;

  // 相对当前根目录的相对路径
  private readonly _mainFileRelativePath: string | undefined;
  private readonly _useNormalizedOHMUrl: boolean | undefined;

  constructor(dependencyBuilder: DependencyBuilder) {
    this._dependencyName = dependencyBuilder.getDependencyName();
    this._dependedVersion = dependencyBuilder.getDependedVersion();
    this._lastDependencyName = dependencyBuilder.getLastDependencyName();
    this._dependencyVersion = dependencyBuilder.getDependencyVersion();
    this._dependencyRootPath = dependencyBuilder.getDependencyRootPath();
    this._dependencies = dependencyBuilder.getDependencies();
    this._pkgJsonPath = dependencyBuilder.getPkgJsonPath();
    this._pkgJsonObj = dependencyBuilder.getPkgJsonObj();
    this._moduleJsonObj = dependencyBuilder.getModuleJsonObj();
    this._useNormalizedOHMUrl = (this._pkgJsonObj as any)?.metadata?.useNormalizedOHMUrl;
    this._pkgJsonName = this._pkgJsonObj.name!; // har/hsp依赖保证必须会存在name字段
    this._mainFilePath = path.resolve(this._dependencyRootPath, this._pkgJsonObj.main || 'index.js');
    this._typesFilePath = path.resolve(this._dependencyRootPath, this._pkgJsonObj.types ?? 'index.d.ts');
    this._mainFileRelativePath = this.getMainFileRelativePath(this._dependencyRootPath, this._pkgJsonObj as OhPackageJsonOpt);
    this._dependencyType = dependencyBuilder.getDependencyType();
    this._dependencyEnum = dependencyBuilder.getDependencyEnum();
    this._isLocal = dependencyBuilder.isLocal();
    this._isModuleDependency = dependencyBuilder.isModuleDependency();
  }

  getPackageJsonPath(): string {
    return this._pkgJsonPath;
  }

  getPackageFilePath(): string {
    return this._pkgJsonPath;
  }

  getPackageJsonObj(): PackageJson {
    return this._pkgJsonObj;
  }

  getPackageName(): string {
    return this._pkgJsonName;
  }

  getModuleName(): string {
    return this.getModuleJsonObj()?.module.name ?? this.getPackageName();
  }

  getDependencyName(): string {
    return this._dependencyName;
  }

  getDependedVersion(): string {
    return this._dependedVersion;
  }

  getDependencyVersion(): string {
    return this._dependencyVersion;
  }

  getDependencyRootPath(): string {
    return this._dependencyRootPath;
  }

  getDependencyMainFilePath(): string {
    return this._mainFilePath;
  }

  getDependencyTypesFilePath(): string {
    return this._typesFilePath;
  }

  getDependencyType(): DependencyType {
    return this._dependencyType;
  }

  getDependencyEnum(): DependencyEnum {
    return this._dependencyEnum;
  }

  getDependencies(): Partial<Record<string, string>> {
    return this._dependencies;
  }

  getModuleJsonObj(): ModuleOptObj | undefined {
    return this._moduleJsonObj;
  }

  getDependencyMainFileRelativePath(): string | undefined {
    return this._mainFileRelativePath;
  }

  getUseNormalizedOHMUrl(): boolean | undefined {
    return this._useNormalizedOHMUrl;
  }

  hasNative(): boolean {
    return fse.existsSync(path.resolve(this._dependencyRootPath, 'libs')) || fse.existsSync(path.resolve(this._dependencyRootPath, 'include'));
  }

  isLocal(): boolean {
    return this._isLocal;
  }

  isByteCodeHarDependency(): boolean {
    const pkgJson = this.getPackageJsonObj() as any;
    return !!pkgJson?.metadata?.byteCodeHar;
  }

  isHarDependency(): boolean {
    return this._dependencyType === DependencyType.DEPENDENCY_TYPE_HAR;
  }

  isHspDependency(): boolean {
    return this._dependencyType === DependencyType.DEPENDENCY_TYPE_HSP;
  }

  isOtherDependency(): boolean {
    return this._dependencyType === DependencyType.DEPENDENCY_TYPE_OTHER;
  }

  isSODependency(): boolean {
    return this._dependencyType === DependencyType.DEPENDENCY_TYPE_SO;
  }

  /**
   * bundle Har的前提必须是一个字节码har
   */
  isBundleDependency(): boolean {
    const pkgJson = this.getPackageJsonObj() as any;
    return this.isByteCodeHarDependency() && !!pkgJson?.metadata?.bundleDependencies;
  }

  getLastDependencyName(): string | undefined {
    return this._lastDependencyName;
  }

  setLastDependencyName(dependencyName: string) {
    this._lastDependencyName = dependencyName;
  }

  getMainFileRelativePath(_dependencyRootPath: string, _pkgJsonObj: OhPackageJsonOpt): string {
    const mainFilePath = getEntryMainFilePath(_dependencyRootPath, _pkgJsonObj);
    return mainFilePath ? toUnixPath(path.relative(this._dependencyRootPath, mainFilePath)) : '';
  }

  getDefaultLibsDir(): string {
    return path.resolve(this._dependencyRootPath, BuildDirConst.LIBS);
  }

  isModuleDependency(): boolean {
    return this._isModuleDependency;
  }

  getDependencySrcMainPath(): string {
    return path.resolve(this.getDependencyRootPath(), BuildDirConst.SRC, BuildDirConst.MAIN);
  }

  getDependencySrcMainResourceBaseProfilePath(): string {
    return path.resolve(this.getDependencySrcMainPath(), BuildDirConst.RESOURCES_BASE_PROFILE_DIR);
  }

  getInsightIntentPath(): string {
    return path.resolve(this.getDependencySrcMainResourceBaseProfilePath(), BuildArtifactConst.INSIGHT_INTENT_JSON)
  }
}
